package bb.lanxing.activity.routebook

import android.bluetooth.BluetoothProfile
import android.content.DialogInterface
import android.content.Intent
import androidx.activity.viewModels
import androidx.appcompat.app.AlertDialog
import androidx.lifecycle.Lifecycle
import androidx.lifecycle.lifecycleScope
import androidx.lifecycle.repeatOnLifecycle
import androidx.recyclerview.widget.DiffUtil.ItemCallback
import bb.lanxing.R
import bb.lanxing.activity.sport.SportActivity
import bb.lanxing.adapter.routebook.DeviceRouteBookAdapter
import bb.lanxing.databinding.ActivityDeviceRouteBookBinding
import bb.lanxing.device.sgdevcie.viewmodel.DeviceViewModel
import bb.lanxing.manager.SPConstant
import bb.lanxing.model.database.RouteBook
import bb.lanxing.model.database.RouteBookInfo
import bb.lanxing.mvvm.base.BaseDBActivity
import bb.lanxing.network.MyHttpClient
import bb.lanxing.util.Log
import bb.lanxing.util.RouteBookUtil
import bb.lanxing.util.text.TextUtils
import bb.lanxing.view.CustomLoadMoreView
import com.bes.bessdk.service.base.BesServiceListener
import com.bes.sdk.device.HmDevice
import com.bes.sdk.message.Constants
import com.bes.sdk.utils.SettingsJsonUtils
import com.besall.allbase.bluetooth.service.Protocol.ProtocolConstants
import com.besall.allbase.bluetooth.service.Protocol.ProtocolService
import com.besall.allbase.common.utils.ActivityUtils.showToast
import com.besall.allbase.view.activity.chipstoollevel4.protocol.ProtocolPresenter
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext
import org.json.JSONObject
import org.litepal.LitePal.where


/**
 * 获取导入过码表的路书
 */
class RouteBookDeviceActivity : BaseDBActivity<ActivityDeviceRouteBookBinding>(),
    BesServiceListener, DialogInterface.OnCancelListener {
    companion object {
        private const val ROUTE_BOOK_IN_DEVICE_LIMIT = 20
        private const val REQUEST_CODE_ROUTE_INFO_ACTIVITY = 101
        private const val REQUEST_CODE_IMPORT_ROUTE_BOOK_ACTIVITY = 102
    }

    private var protocolService: ProtocolService? = null
    private val deviceViewModel by viewModels<DeviceViewModel>()
    private val adapter by lazy {
        DeviceRouteBookAdapter().apply {
            loadMoreModule.apply {
                loadMoreView = CustomLoadMoreView()
                isAutoLoadMore = false
                isEnableLoadMore = false
                isEnableLoadMoreIfNotFullPage = false
                addChildClickViewIds(R.id.ll_delete)
                setOnItemClickListener { _, _, position ->
                    run {
                        val routeBook = data[position]
                        val intent = Intent(
                            this@RouteBookDeviceActivity, RouteBookInfoActivity::class.java
                        )
                        val lushuId = routeBook.getId()
                        if (null != lushuId) {
                            intent.putExtra(SportActivity.EXTRA_LUSHU_ID, lushuId)
                        }
                        val serverId = routeBook.serverId
                        if (0L != serverId) {
                            intent.putExtra(SPConstant.KEY_SERVER_ID, serverId)
                        }
                        startActivityForResult(intent, REQUEST_CODE_ROUTE_INFO_ACTIVITY)
                    }
                }
                setOnItemChildClickListener { _, view, position ->
                    run {
                        val lushu = data[position]
                        if (view.id == R.id.ll_delete) {
                            buildDeleteDialog(lushu)
                        }
                    }
                }
            }
            setDiffCallback(object : ItemCallback<RouteBook>() {
                override fun areItemsTheSame(oldItem: RouteBook, newItem: RouteBook): Boolean {
                    return oldItem.serverId == newItem.serverId
                }

                override fun areContentsTheSame(oldItem: RouteBook, newItem: RouteBook): Boolean {
                    return oldItem.serverId == newItem.serverId && oldItem.updateTime == newItem.updateTime
                }
            })
        }
    }
    var deviceAddress: String? = null
    var deviceModel: String? = null
    var deviceName: String? = null
    var type: Int? = null
    private var routebookCount = 0

    override fun getLayoutId() = R.layout.activity_device_route_book

    override fun initView(t: ActivityDeviceRouteBookBinding) {
        setupActionBar(true)
        val stringExtra = intent.getStringExtra("EXTRA_DEVICE_ADDRESS")
        deviceAddress = stringExtra
        val stringExtra2 = intent.getStringExtra("EXTRA_DEVICE_MODEL") ?: ""
        deviceModel = stringExtra2
        val stringExtra3 = intent.getStringExtra("EXTRA_DEVICE_NAME") ?: ""
        deviceName = stringExtra3
        val intExtra4 = intent.getIntExtra("EXTRA_DEVICE_TYPE", 28)
        type = intExtra4
        val sb = StringBuilder()
        if (!TextUtils.isEmptyOrNull(deviceModel)) {
            sb.append(deviceModel)
            sb.append("/")
        }
        if (!TextUtils.isEmptyOrNull(deviceName)) {
            sb.append(deviceName)
            sb.append("/")
        }
        sb.append(getString(R.string.lushu))
        setTitle(sb.toString())

        binding.refreshLayout.setOnRefreshListener(::getRouteList)
        binding.rvRoutebookList.adapter = adapter
        binding.btnImport.setOnClickListener {
            launchImport(deviceAddress, type, deviceName)
        }
        setBtnText()
        lifecycleScope.launch {
            repeatOnLifecycle(Lifecycle.State.CREATED) {
                deviceViewModel.routeBookListFlow.collect { routeBooks ->
                    routeBooks.apply {
                        routes.apply {
                            if (isNotEmpty()) {
                                val localRouteBookList = RouteBook.getList()
                                val syncLocalRouteBookList = mutableListOf<RouteBook>()
                                val localMissRouteBookIds = mutableListOf<Long>()
                                routebookCount = size
                                for (route in this) {
                                    val rid = route.rid.toLong()
                                    var find = false
                                    if (localRouteBookList.isNotEmpty()) {
                                        for (localRouteBook in localRouteBookList) {
                                            if (localRouteBook.serverId == rid) {
                                                syncLocalRouteBookList.add(localRouteBook)
                                                find = true
                                                break
                                            }
                                        }
                                    }
                                    if (!find) {
                                        localMissRouteBookIds.add(rid)
                                    }
                                }
                                if (localMissRouteBookIds.isNotEmpty()) {
                                    withContext(Dispatchers.IO) {
                                        val serverMissRouteBookIds = mutableListOf<Long>()
                                        for (item in localMissRouteBookIds) {
                                            try {
                                                MyHttpClient.downloadRouteBookSync(item).body()
                                                    ?.let {
                                                        val s = it.string()
                                                        val jsonObject = JSONObject(s)
                                                        val jsonObjectData =
                                                            jsonObject.getJSONObject("data")
                                                        val id = RouteBookUtil.parseBDDirectionNew(
                                                            jsonObjectData, null, null
                                                        )
                                                        syncLocalRouteBookList.add(
                                                            RouteBook.getById(id)
                                                        )
                                                    }
                                                MyHttpClient.downloadRouteBookFileSync(item).body()
                                                    ?.let {
                                                        val s = it.string()
                                                        val routeBookInfo: RouteBookInfo
                                                        val jsonObject = JSONObject(s)
                                                        val msg = jsonObject.getString("msg")
                                                        val ext = jsonObject.getString("ext")
                                                        val content =
                                                            jsonObject.getString("content")
                                                        val json_url = jsonObject.getString("name")
                                                        val distance =
                                                            jsonObject.getDouble("distance")
                                                        val size = jsonObject.getInt("fileSize")
                                                        val type = jsonObject.getString("sportType")
                                                        val version =
                                                            jsonObject.getString("version")
                                                        val source = jsonObject.getInt("sourceType")
                                                        val gain =
                                                            jsonObject.getDouble("elevationGain")
                                                                .toInt()
                                                        val title = jsonObject.getString("title")
                                                        val filePath =
                                                            RouteBookUtil.saveDirectionFile(
                                                                content, item, ext
                                                            )
                                                        val list = where(
                                                            "serverId = ?", item.toString()
                                                        ).find<RouteBookInfo>(
                                                            RouteBookInfo::class.java
                                                        )
                                                        routeBookInfo = if (list.isNotEmpty()) {
                                                            list[0]
                                                        } else {
                                                            RouteBookInfo()
                                                        }
                                                        routeBookInfo.json_url = json_url
                                                        routeBookInfo.title = title
                                                        routeBookInfo.distance = distance
                                                        routeBookInfo.sourceType = source
                                                        routeBookInfo.sportType = type
                                                        routeBookInfo.elevationGain = gain
                                                        routeBookInfo.serverId = item.toString()
                                                        routeBookInfo.filePath = filePath
                                                        routeBookInfo.ext = ext
                                                        routeBookInfo.save()
                                                    }
                                            } catch (e: Throwable) {
                                                e.printStackTrace()
                                                serverMissRouteBookIds.add(item)
                                            }
                                        }
                                        if (serverMissRouteBookIds.isNotEmpty()) {
                                            dismissLoadingDialog()
                                            toast(R.string.routebook_not_exist)
                                        } else if (syncLocalRouteBookList.size != routebookCount) {
                                            dismissLoadingDialog()
                                            toast(R.string.re_refresh)
                                        } else {
                                            runOnUiThread {
                                                setBtnText()
                                                dismissLoadingDialog()
                                                adapter.setList(syncLocalRouteBookList)
                                            }
                                        }
                                    }
                                } else {
                                    setBtnText()
                                    dismissLoadingDialog()
                                    adapter.setList(syncLocalRouteBookList)
                                }
                            } else {
                                dismissLoadingDialog()
                            }
                        }
                    }
                }
            }
        }
        lifecycleScope.launch {
            repeatOnLifecycle(Lifecycle.State.STARTED) {
                deviceViewModel.routebooksNotExist.collect { result ->
                    if (result) {
                        emptyRouteList(R.string.routebook_not_exist)
                    }
                }
            }
        }
        lifecycleScope.launch {
            repeatOnLifecycle(Lifecycle.State.STARTED) {
                deviceViewModel.exceptionMessage.collect { msg ->
                    emptyRouteList(msg)
                }
            }
        }

        getRouteList()
    }

    private fun getRouteBookList() {
        deviceViewModel.getRouteBookList()
    }

    private fun dismissRefresh() {
        binding.refreshLayout.isRefreshing = false
    }

    private fun launchImport(address: String?, type: Int?, name: String?) {
        val intent = Intent(context, RouteBookImportActivity::class.java)
        intent.putExtra("EXTRA_DEVICE_ADDRESS", address)
        intent.putExtra("EXTRA_DEVICE_TYPE", type)
        intent.putExtra("EXTRA_DEVICE_NAME", name)
        startActivityForResult(intent, REQUEST_CODE_IMPORT_ROUTE_BOOK_ACTIVITY)
    }

    private fun setBtnText() {
        dismissRefresh()
        if (routebookCount == 0) {
            binding.btnImport.text = getString(R.string.import_routebook)
        } else {
            binding.btnImport.text =
                getString(R.string.import_routebook) + "($routebookCount/$ROUTE_BOOK_IN_DEVICE_LIMIT)"
        }
    }

    private fun buildDeleteDialog(routeBook: RouteBook) {
        val builder = AlertDialog.Builder(this)
        builder.setMessage(R.string.route_book_delete_dialog_content)
        builder.setPositiveButton(
            R.string.confirm
        ) { _, _ -> deleteRoutebookInDevice(routeBook) }
        builder.setNegativeButton(R.string.cancel) { _, _ ->
            {}
        }
        builder.show()
    }

    private fun deleteRoutebookInDevice(routeBook: RouteBook) {
    }

    override fun onTotaConnectState(state: Boolean, hmDevice: HmDevice?) {
        Log.i("DeviceRouteBookActivity onTotaConnectState state = $state")
    }

    override fun onErrorMessage(msg: Int, hmDevice: HmDevice?) {
        Log.i("DeviceRouteBookActivity onErrorMessage msg = $msg")
        if (msg == Constants.NO_JSON_FILE_EXIST) {
            emptyRouteList(R.string.routebook_not_exist)
        }
    }

    override fun onStateChangedMessage(msg: Int, msgStr: String?, hmDevice: HmDevice?) {
        Log.i("DeviceRouteBookActivity onStateChangedMessage msg = $msg,msgStr = $msgStr")
    }

    override fun onSuccessMessage(msg: Int, hmDevice: HmDevice?) {
        Log.i("DeviceRouteBookActivity onSuccessMessage msg = $msg")
        if (msg == Constants.SAVE_ROUTE_JSON_FILE_SUCCESS) {
            getRouteBookList()
        }
    }

    private fun getRouteList() {
        val protocolPresenter = ProtocolPresenter.getInstance()
        protocolPresenter.setProtocolServiceListener(this)
        protocolService = protocolPresenter.protocolService
        if (null != protocolService) {
            val state =
                protocolService?.getDeviceConnectState() ?: BluetoothProfile.STATE_DISCONNECTED
            if (state != BluetoothProfile.STATE_CONNECTED) {
                showToast(R.string.pls_conn_device)
                return
            }
        } else {
            showToast(R.string.pls_conn_device)
            return
        }

        showLoadingDialog(R.string.st_syncing, this)
        protocolPresenter.getBikeWatchDataFromBesClient(
            ProtocolConstants.BIKEWATCH_GET_ROUTE_BOOKS_INFO,
            SettingsJsonUtils.getDeviceModel(this),
            SettingsJsonUtils.getSn(this)
        )
    }

    private fun emptyRouteList(msg: Int) {
        routebookCount = 0
        runOnUiThread {
            setBtnText()
            dismissLoadingDialog()
            snack(msg)
        }
    }

    override fun onCancel(dialog: DialogInterface?) {
        protocolService?.bikewatch_send_giveup_trans_file(this)
    }

    override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
        super.onActivityResult(requestCode, resultCode, data)
        getRouteList()
    }
}